package com.wlf.server.common.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wlf.server.common.em.CacheKey;
import com.wlf.server.common.em.Const;
import com.wlf.server.common.entity.NoticeUser;
import com.wlf.server.common.entity.SysNotice;
import com.wlf.server.common.entity.SysUser;
import com.wlf.server.common.mapper.SysNoticeMapper;
import com.wlf.server.common.ws.NioWebSocketChannelPool;
import com.wlf.server.common.ws.WsBean;
import com.wlf.server.web.dto.MappingDTO;
import com.wlf.server.web.dto.NoticeDTO;
import com.wlf.server.web.dto.ParamPage;
import com.wlf.server.web.dto.UserDTO;
import com.wlf.server.web.util.AjaxBean;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

@Service
@CacheConfig(cacheNames = CacheKey.notice)
public class SysNoticeService extends ServiceImpl<SysNoticeMapper, SysNotice> {
    @Resource
    private MappingDTO mappingDTO;
    @Resource
    private SysUserService userService;
    @Resource
    private NioWebSocketChannelPool channelPool;


    /**
     * 根据ID获取公告
     *
     * @param id ID
     * @return 通知
     */
    @Cacheable(key = "#id")
    public AjaxBean get(String id) {
        return AjaxBean.getOkData(mappingDTO.toDTO(this.getById(id)));
    }

    /**
     * 分页列表数据
     *
     * @param dto       查询参数
     * @param paramPage 分页
     * @return 数据
     */
    public AjaxBean list(NoticeDTO dto, ParamPage paramPage) {
        LambdaQueryWrapper<SysNotice> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(dto.getTitle())){
            wrapper.like(SysNotice::getTitle,dto.getTitle());
        }
        wrapper.orderByDesc(SysNotice::getId);
        Page<SysNotice> page = this.page(paramPage.init(), wrapper);
        List<NoticeDTO> noticeDTOS = mappingDTO.toNoticeDTO(page.getRecords());
        for (NoticeDTO noticeDTO : noticeDTOS) {
            UserDTO user = userService.getUser(noticeDTO.getCreateBy());
            noticeDTO.setCreateByName(user.getName());
            noticeDTO.setAvatar(user.getAvatar());
        }
        return AjaxBean.getOkPage(page).setData(noticeDTOS);
    }


    /**
     * 保存或者更新 公告
     *
     * @param dto 参数
     * @return 操作结果
     */


    @CachePut(key = "#dto.id", condition = "#dto.id != null ")
    public AjaxBean saveOrUpdate(NoticeDTO dto) {
        if (StrUtil.isBlank(dto.getId())){
            dto.setId(IdWorker.getIdStr());
        }
        dto.setCreateTime(LocalDateTime.now());
        dto.setCreateBy(StpUtil.getLoginIdAsString());
        // 如果已经是已发布状态
        if (Const.NoticeType.release.name().equals(dto.getType())) {
            // 自己发送默认已读
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setNoticeId(dto.getId());
            noticeUser.setUserId(StpUtil.getLoginIdAsString());
            noticeUser.setReadTime(LocalDateTime.now());
            Db.save(noticeUser);
            //服务器向浏览器推送消息
            for (SysUser user : userService.list()) {
                // 不推送给自己
                if (StpUtil.getLoginIdAsString().equals(user.getId())) {
                    continue;
                }
                channelPool.sendToUser(user.getId(), WsBean.get(WsBean.CallBackEm.notice,dto));
            }
        }
        return AjaxBean.getByBool(Db.saveOrUpdate(mappingDTO.to(dto)));
    }

    /**
     * 根据ID删除通告
     *
     * @param id ID
     * @return 操作结果
     */
    @CacheEvict(key = "#id", condition = "#id != null ")
    public AjaxBean del(String id) {
        // 删除关联表中的信息
        Db.lambdaUpdate(NoticeUser.class).eq(NoticeUser::getNoticeId, id).remove();
        return AjaxBean.getByBool(this.removeById(id));
    }

    /**
     * 获取一年的通知
     *
     * @return 通知列表
     */
    public AjaxBean getToolList() {
        List<SysNotice> list = this.lambdaQuery()
                .between(SysNotice::getCreateTime
                        , LocalDateTime.now().minusYears(1L)
                        , LocalDateTime.now())
                .eq(SysNotice::getType,Const.NoticeType.release)
                .orderByDesc(SysNotice::getCreateTime)
                .list();
        List<NoticeDTO> noticeDTOS = mappingDTO.toNoticeDTO(list);
        for (NoticeDTO dto : noticeDTOS) {
            if (Db.lambdaQuery(NoticeUser.class)
                    .eq(NoticeUser::getNoticeId, dto.getId())
                    .eq(NoticeUser::getUserId, StpUtil.getLoginIdAsString()).exists()) {
                dto.setReadStatus("Y");
            } else {
                dto.setReadStatus("N");
            }
            UserDTO user = userService.getUser(dto.getCreateBy());
            dto.setCreateByName(user.getName());
            dto.setAvatar(user.getAvatar());
        }

        return AjaxBean.getOkData(noticeDTOS);
    }

    /**
     * 确认收到通知
     *
     * @param id 通知ID
     * @return 操作结果
     */
    public AjaxBean reading(String id) {
        NoticeUser noticeUser = new NoticeUser();
        String userId = StpUtil.getLoginIdAsString();
        noticeUser.setNoticeId(id);
        noticeUser.setUserId(userId);
        noticeUser.setReadTime(LocalDateTime.now());
        NoticeUser one = Db.lambdaQuery(NoticeUser.class)
                .eq(NoticeUser::getNoticeId, id)
                .eq(NoticeUser::getUserId, userId)
                .one();
        if (one == null) {
            return AjaxBean.getByBool(Db.save(noticeUser));
        }
        return AjaxBean.getOkMsg();
    }
}
